/* ====================================================
#   Copyright (C)2019 Li Jianbin All rights reserved.
#
#   Author        : Li Jianbin
#   Email         : lijianbinmail@163.com
#   File Name     : c3dwidget.h
#   Last Modified : 2019-04-21 15:00
#   Describe      : 3D Widget
#
# ====================================================*/

#ifndef C3DWIDGET_H
#define C3DWIDGET_H

#include <QMetaType>
#include <QDataStream>
#include <QTextStream>
#include <QWidget>
#include <QMouseEvent>
#include <QWheelEvent>
#include <QKeyEvent>
#include <QScopedPointer>
#include <QApplication>
#include <QRubberBand>
#include <QStyleFactory>

#include <AIS_InteractiveContext.hxx>
#include <OpenGl_GraphicDriver.hxx>
#include <V3d_View.hxx>
#include <Aspect_Handle.hxx>
#include <Aspect_DisplayConnection.hxx>
#include <Graphic3d_GraphicDriver.hxx>

#include <QGLWidget>
#ifdef _WIN32
#include <WNT_Window.hxx>
#else
#undef None
#include <Xw_Window.hxx>
#endif

#include <BRepPrimAPI_MakeSphere.hxx>
#include <BRepPrimAPI_MakeCone.hxx>
#include <BRepPrimAPI_MakeTorus.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#include <BRepPrimAPI_MakeBox.hxx>
#include <AIS_Shape.hxx>

// Project Include
#include "cmodel.h"
#include "src/pub/publics.h"
#include <thread>
#include <future>

#include <Graphic3d_ArrayOfPoints.hxx>
#include <AIS_PointCloud.hxx>


/*　点云　*/
#include <V3d_AmbientLight.hxx>
#include <V3d_DirectionalLight.hxx>
#include <Geom_CartesianPoint.hxx>
#include <StdPrs_Point.hxx>

/*　动画　*/
#include <AIS_Animation.hxx>
#include <AIS_AnimationObject.hxx>

/*　异常　*/
#include <Standard_Failure.hxx>
#include <Standard_ErrorHandler.hxx>

/*　模型控制　*/
#include <AIS_Manipulator.hxx>

/*  三维坐标系  */
#include <AIS_ViewCube.hxx>

/*  三维坐标系  */
#include <Graphic3d_Camera.hxx>


///
/// \brief 三维显示窗口
///
class C3DWidget : public QGLWidget
{
    Q_OBJECT
public:
    explicit C3DWidget(QWidget *parent = nullptr);
    //! 生成立方体
    void make_cube(Standard_Real _dx = 1.0, Standard_Real _dy = 1.0, Standard_Real _dz = 1.0);
    //! 生成圆柱
    void make_cylinder(Standard_Real _R = 0.5,  Standard_Real _H = 2.0);
    //! 球体
    void make_sphere(Standard_Real _R = 100.0);
    //! 生成圆锥
    void make_cone(Standard_Real _R1 = 1.0, Standard_Real _R2 = 0.0, Standard_Real _H = 2.0);
    //! 生成圆环体
    void make_torus(Standard_Real _R1 =2.0, Standard_Real _R2 = 0.5);

    //! 获取三维环境交互对象
    Handle(AIS_InteractiveContext) m_get_context(){return m_context;}

    //! 获取三维显示界面
    Handle(V3d_View)  m_get_view(){return m_view;}

    //! 获取三维显示界面
    Handle(V3d_Viewer)  m_get_viewer(){return m_viewer;}

    //! 移除当前选择的模型
    void removeCurModel(){
        m_context->Remove(m_context->Current(),Standard_True);
    }
    //! 绑定控制器到模型中
    void attachToPulator(const Handle(AIS_InteractiveObject)& aobj);

    //! 绝对运动
    void setLocation(const Handle(AIS_InteractiveObject)& aShape, Pos3dzx pos,bool allowAnimation = false);
    void SetModelLocation(const Handle(AIS_InteractiveObject)& aShape,gp_Trsf trsf,bool allowAnimation = false);

    //! 相对运动
    void relativeMove(const Handle(AIS_InteractiveObject)& aShape, Pos3dzx pos);
    //! 绑定操作器具
    void bindCoordinate(const Handle(AIS_InteractiveObject)& aShape);
    //! 设置鼠标的默认模式
    void setDefaultMouse(int mod);



public slots:
    void showSomePath(std::vector<Pos3dzx>);    // 显示轨迹
    void showPolygonPath(std::vector<Pos3dzx>);
    void showAxles(std::vector<Pos3dzx>);      // 显示坐标系
    void setCameraPosition(Pos3dzx);           // 修改相机的位置
    void setCameraRelativePosition(gp_Pnt);   // 修改相机的位置
    void setRelateParament(ControlIndex index,int val);
    //! 模拟动画
    void genAnimations(std::vector<Pos3dzx>);
private:
    //! 初始化交互环境
    void m_initialize_context();
    //! 交互式上下文能够管理一个或多个查看器(viewer)中的图形行为和交互式对象的选择
    Handle(AIS_InteractiveContext) m_context;
    //! 定义查看器(viewer)类型对象上的服务
    Handle(V3d_Viewer) m_viewer;
    //! 创建一个视图
    Handle(V3d_View) m_view;
    //! 创建3d接口定义图形驱动程序
    Handle(Graphic3d_GraphicDriver) m_graphic_driver;

    Handle(Graphic3d_Camera) scaneCam;

protected:
    //! 覆写绘图事件
    void paintEvent(QPaintEvent *);
    //! 覆写窗口尺寸变化事件
    void resizeEvent(QResizeEvent *);
    //! 覆写鼠标按键按下事件
    void mousePressEvent(QMouseEvent *event);
    //! 覆写鼠标按键释放事件
    void mouseReleaseEvent(QMouseEvent *event);
    //! 覆写鼠标移动事件
    void mouseMoveEvent(QMouseEvent *event);
    //! 覆写鼠标滚轮事件
    void wheelEvent(QWheelEvent *event);
    //! 覆写鼠标双击事件
    void mouseDoubleClickEvent(QMouseEvent *event);
protected slots:
    //! 覆写键盘按键事件
    void keyPressEvent(QKeyEvent *e);
    void keyReleaseEvent(QKeyEvent *e);

protected:
    //! 三维场景转换模式 & 左键三维选择模式
    enum CurrentAction3d
    {
        CurAction3d_Nothing = 0,
        CurAction3d_DynamicZooming,  // 场景缩放
        CurAction3d_DynamicPanning,  // 场景平移
        CurAction3d_DynamicRotation, // 场景旋转
        CurAction3d_Selecte,         // 对象选择
        SelectAction3d_Pann,         // 模型控制
    };


private:
    Standard_Integer m_x_max;    //!记录鼠标平移坐标X
    Standard_Integer m_y_max;    //!记录鼠标平移坐标Y
    CurrentAction3d m_current_mode = CurAction3d_Nothing; //!三维场景转换模式
    CurrentAction3d default_mode = CurAction3d_Nothing; //!三维场景转换模式
    AIS_StatusOfPick t_pick_status = AIS_SOP_NothingSelected;
    Handle(AIS_Manipulator) aManipulator;   //! 模型操控器--blender类似
    Handle(AIS_ViewCube) aViewCube;         //! 模型操控器--坐标系盒子
    Handle(AIS_Animation) ais_animation;    //! 动画模型


    bool isMPressed = false;    // space按键是否被按下
    bool isVPressed = false;        // V按键是否被按下


public :
    bool IsCommon();

    void getDescs();


private slots:
    void updateCurrentScense();
signals:
    void showPosition(Pos3dzx);         //! 提交pos-move信息
    void startAnimation();

private:
    void setMuliModel(bool);                //! 设置多选-单选
    void updatePos(QMouseEvent *event);     //! 更新pos信息
    void drawRubberBand(QPoint ,QPoint);    //! 绘制放大面板
    void windowFit(QPoint ,QPoint);         //! 更新当前放大视图
    void CreatAnimation();                  //! 创建动画线程
    QRubberBand m_rubberBand;               //! 缩放板对象
    QPoint  startPos;                       //! 记录缩放起点
    bool   drawRubbing = false;             //! 是否正在绘制中
    std::atomic<bool> isMoving = ATOMIC_FLAG_INIT;
};

#endif // C3DWIDGET_H
